/**
 * Notes: 预约模块业务逻辑 - 宠物门店预约小程序
 * Date: 2025-01-27 
 */

const BaseService = require('./base_service.js');
const AppointmentModel = require('../model/appointment_model.js');
const RechargeModel = require('../model/recharge_model.js');
const StoreModel = require('../model/store_model.js');
const ServiceModel = require('../model/service_model.js');
const PetModel = require('../model/pet_model.js');
const timeUtil = require('../../framework/utils/time_util.js');

class AppointmentService extends BaseService {

	/**
	 * 创建预约单
	 * @param {string} userId 用户ID
	 * @param {Object} appointmentData 预约数据
	 * @returns {Object} 创建结果
	 */
	async createAppointment(userId, appointmentData) {
		let {
			storeId,
			serviceId,
			petIds,
			appointmentTime,
			employeeId,
			deviceId,
			couponId,
			contactName,
			contactPhone,
			remarks,
			totalAmount,
			totalDays,
			roomType,
			roomUnit
		} = appointmentData;

		// 验证必填字段
		if (!storeId || !serviceId || !petIds || !appointmentTime) {
			throw new Error('门店、服务、宠物和预约时间为必填项');
		}

		// 验证门店是否存在
		const store = await StoreModel.getOne({ _id: storeId });
		if (!store) {
			throw new Error('门店不存在');
		}

		// 验证服务是否存在
		const service = await ServiceModel.getOne({ _id: serviceId });
		if (!service) {
			throw new Error('服务不存在');
		}

		// 验证宠物是否属于用户
		for (let petId of petIds) {
			const pet = await PetModel.getOne({ _id: petId, userId: userId });
			if (!pet) {
				throw new Error('宠物不存在或无权限操作');
			}
		}

		// 计算预约结束时间
		// 对于按天计费的寄养服务（roomUnit === '天'），应该基于totalDays计算
		// 对于按小时计费的服务，使用service.duration计算
		let appointmentEndTime;
		if (roomUnit === '天' && totalDays && totalDays > 0) {
			// 寄养服务：开始日期 + (总天数 - 1) * 一天的秒数
			// 例如：11-26开始，4天，结束时间应该是11-29晚上
			// appointmentTime 是开始日期的某个时间点（如早上9点）
			// 结束时间应该是开始时间 + (totalDays - 1) * 24 * 3600，再设置为当天晚上（如18:00）
			const daysInSeconds = (totalDays - 1) * 24 * 3600; // (天数-1) * 一天的秒数
			const endTimeBase = appointmentTime + daysInSeconds;
			// 将结束时间设置为当天的18:00（寄养结束时间）
			// 获取结束日期
			const endDate = new Date(endTimeBase * 1000); // 转换为毫秒
			endDate.setHours(18, 0, 0, 0); // 设置为18:00
			appointmentEndTime = Math.floor(endDate.getTime() / 1000); // 转回秒时间戳
		} else {
			// 按小时计费或其他服务，使用service.duration计算
			appointmentEndTime = appointmentTime + (service.duration * 60);
		}

		// 检查时间冲突（先检查宠物是否已有预约，再检查房间容量）
		await this.checkTimeConflict(storeId, serviceId, appointmentTime, appointmentEndTime, employeeId, deviceId, null, userId, petIds);

		// 计算金额 - 优先使用前端传递的总价
		const finalTotalAmount = totalAmount || service.price;
		const payAmount = finalTotalAmount; // 暂时不考虑优惠券

		// 生成预约单号
		const appointmentNumber = this.generateAppointmentNumber();

		let data = {
			_pid: 'A00', // 添加项目ID
			_id: this.generateId(),
			appointmentNumber: appointmentNumber,
			userId: userId,
			petIds: petIds,
			storeId: storeId,
			serviceId: serviceId,
			employeeId: employeeId || '',
			deviceId: deviceId || '',
			appointmentTime: appointmentTime,
			appointmentEndTime: appointmentEndTime,
			status: AppointmentModel.STATUS.PENDING_PAY,
			totalAmount: finalTotalAmount,
			payAmount: payAmount,
			payTime: 0,
			contactName: contactName || '',
			contactPhone: contactPhone || '',
			remarks: remarks || '',
			roomType: roomType || '',
			roomUnit: roomUnit || '天',
			totalDays: totalDays || 1,
			createTime: Math.floor(timeUtil.time() / 1000), // 转换为秒时间戳
			updateTime: Math.floor(timeUtil.time() / 1000) // 转换为秒时间戳
		};

		console.log('保存预约数据:', {
			contactName: data.contactName,
			contactPhone: data.contactPhone,
			remarks: data.remarks
		});

		await AppointmentModel.insert(data, false);
		return data;
	}

	/**
	 * 获取用户订单列表（包括预约订单和充值订单）
	 * @param {string} userId 用户ID
	 * @param {number} status 状态筛选
	 * @param {number} page 页码
	 * @param {number} size 每页数量
	 * @returns {Object} 订单列表
	 */
	async getUserAppointments(userId, status = null, page = 1, size = 20) {
		// 在查询前取消用户所有待支付的充值订单
		const rechargeModel = new RechargeModel();
		await rechargeModel.cancelUserPendingOrders(userId);
		
		// 获取预约订单（排除已删除的订单）
		let appointmentWhere = { 
			userId: userId,
			isDeleted: { $ne: 1 } // 排除已删除的订单
		};
		if (status !== null) {
			appointmentWhere.status = status;
		}

		let appointmentFields = '_id,appointmentNumber,storeId,serviceId,petIds,appointmentTime,appointmentEndTime,status,totalAmount,payAmount,contactName,contactPhone,remarks,createTime,updateTime,payTime';
		let orderBy = { createTime: -1 };

		const appointmentResult = await AppointmentModel.getList(appointmentWhere, appointmentFields, orderBy, page, Math.ceil(size/2), true, 0);
		
		// 获取充值订单
		let rechargeWhere = { userId: userId };
		if (status !== null) {
			// 映射充值订单状态到预约订单状态
			const rechargeStatus = this.mapAppointmentStatusToRechargeStatus(status);
			if (rechargeStatus !== null) {
				rechargeWhere.status = rechargeStatus;
			}
		}

		let rechargeFields = '_id,orderNumber,amount,bonus,totalAmount,status,createTime,payTime';
		const rechargeResult = await RechargeModel.getList(rechargeWhere, rechargeFields, orderBy, page, Math.ceil(size/2), true, 0);
		
		// 转换充值订单为统一格式
		const rechargeOrders = rechargeResult.list.map(order => this.convertRechargeToAppointmentFormat(order));
		
		// 补充预约订单关联信息
		const appointments = await this.enrichAppointmentList(appointmentResult.list);
		
		// 合并两种订单并按创建时间排序
		const allOrders = [...appointments, ...rechargeOrders];
		allOrders.sort((a, b) => b.createTime - a.createTime);
		
		// 分页处理
		const startIndex = (page - 1) * size;
		const endIndex = startIndex + size;
		const paginatedOrders = allOrders.slice(startIndex, endIndex);
		
		return {
			list: paginatedOrders,
			total: appointmentResult.total + rechargeResult.total,
			page: page,
			size: size
		};
	}

	/**
	 * 获取预约详情
	 * @param {string} appointmentId 预约ID
	 * @param {string} userId 用户ID
	 * @returns {Object} 预约详情
	 */
	async getAppointmentDetail(appointmentId, userId) {
		let where = {
			_id: appointmentId,
			userId: userId
		};
		// 添加roomType、roomUnit、totalDays字段，确保前端能获取到完整的预约信息
		let fields = '_id,appointmentNumber,userId,petIds,storeId,serviceId,employeeId,deviceId,appointmentTime,appointmentEndTime,status,totalAmount,payAmount,payTime,contactName,contactPhone,remarks,roomType,roomUnit,totalDays,createTime,updateTime';
		
		const appointment = await AppointmentModel.getOne(where, fields);
		if (!appointment) {
			throw new Error('预约单不存在或无权限操作');
		}

		return await this.enrichAppointmentDetail(appointment);
	}

	/**
	 * 更新预约状态
	 * @param {string} appointmentId 预约ID
	 * @param {number} status 新状态
	 * @param {string} userId 用户ID（可选，用于权限验证）
	 * @returns {Object} 更新结果
	 */
	async updateAppointmentStatus(appointmentId, status, userId = null) {
		let where = { _id: appointmentId };
		if (userId) {
			where.userId = userId;
		}

		// 检查预约是否存在
		const appointment = await AppointmentModel.getOne(where);
		if (!appointment) {
			throw new Error('预约单不存在或无权限操作');
		}

		// 验证状态转换是否合法
		if (!this.isValidStatusTransition(appointment.status, status)) {
			throw new Error('状态转换不合法');
		}

		let updateData = {
			status: status,
			updateTime: timeUtil.time()
		};

		// 如果是支付状态，记录支付时间
		if (status === AppointmentModel.STATUS.PAID) {
			updateData.payTime = timeUtil.time();
		}

		await AppointmentModel.edit(where, updateData);
		return await this.getAppointmentDetail(appointmentId, appointment.userId);
	}

	/**
	 * 取消预约
	 * @param {string} appointmentId 预约ID
	 * @param {string} userId 用户ID
	 * @returns {boolean} 取消结果
	 */
	async cancelAppointment(appointmentId, userId) {
		let where = {
			_id: appointmentId,
			userId: userId
		};

		// 检查预约是否存在
		const appointment = await AppointmentModel.getOne(where);
		if (!appointment) {
			throw new Error('预约单不存在或无权限操作');
		}

		// 只有待支付和已支付状态可以取消
		if (appointment.status !== AppointmentModel.STATUS.PENDING_PAY && 
			appointment.status !== AppointmentModel.STATUS.PAID) {
			throw new Error('当前状态不允许取消');
		}

		await AppointmentModel.edit(where, {
			status: AppointmentModel.STATUS.CANCELLED,
			updateTime: timeUtil.time()
		});

		return true;
	}

	/**
	 * 删除预约（软删除，仅对已取消的订单）
	 * @param {string} appointmentId 预约ID
	 * @param {string} userId 用户ID
	 * @returns {boolean} 删除结果
	 */
	async deleteAppointment(appointmentId, userId) {
		let where = {
			_id: appointmentId,
			userId: userId
		};

		// 检查预约是否存在
		const appointment = await AppointmentModel.getOne(where);
		if (!appointment) {
			throw new Error('预约单不存在或无权限操作');
		}

		// 只有已取消的订单可以删除
		if (appointment.status !== AppointmentModel.STATUS.CANCELLED) {
			throw new Error('只有已取消的订单可以删除');
		}

		// 软删除：设置 isDeleted = 1
		await AppointmentModel.edit(where, {
			isDeleted: 1,
			updateTime: timeUtil.time()
		});

		return true;
	}

	/**
	 * 检查时间冲突
	 * @param {string} storeId 门店ID
	 * @param {string} serviceId 服务ID
	 * @param {number} startTime 开始时间
	 * @param {number} endTime 结束时间
	 * @param {string} employeeId 员工ID
	 * @param {string} deviceId 设备ID
	 * @param {string} excludeAppointmentId 排除的预约ID（用于更新时排除自身）
	 * @param {string} userId 用户ID（用于检查宠物预约冲突）
	 * @param {Array} petIds 宠物ID列表（用于检查宠物预约冲突）
	 */
	async checkTimeConflict(storeId, serviceId, startTime, endTime, employeeId, deviceId, excludeAppointmentId = null, userId = null, petIds = null) {
		// 第一步：检查该宠物是否已有预约（优先级最高）
		if (userId && petIds && Array.isArray(petIds) && petIds.length > 0) {
			let petConflictWhere = {
				userId: userId,
				petIds: { $in: petIds },
				status: { $in: [AppointmentModel.STATUS.PENDING_PAY, AppointmentModel.STATUS.PAID, AppointmentModel.STATUS.IN_SERVICE] },
				isDeleted: { $ne: 1 }
			};
			if (excludeAppointmentId) {
				petConflictWhere._id = { $ne: excludeAppointmentId };
			}
			// 检查时间重叠
			petConflictWhere.$or = [
				{ appointmentTime: { $gte: startTime, $lt: endTime } },
				{ appointmentEndTime: { $gt: startTime, $lte: endTime } },
				{ appointmentTime: { $lte: startTime }, appointmentEndTime: { $gte: endTime } }
			];
			
			const petConflicts = await AppointmentModel.getAll(petConflictWhere);
			if (petConflicts.length > 0) {
				throw new Error('PET_CONFLICT:该宠物已有预约，请选择其他时段');
			}
		}

		// 第二步：检查房间/服务容量
		// 获取服务信息以确定容量
		const service = await ServiceModel.getOne({ _id: serviceId }, 'quantity');
		const capacity = service && typeof service.quantity === 'number' && service.quantity > 0 ? service.quantity : 0;

		if (capacity > 0) {
			// 针对具体服务进行容量校验：统计时间段内该服务的并发预约数（包含待支付以避免超售）
			let where = {
				storeId: storeId,
				serviceId: serviceId,
				status: { $in: [AppointmentModel.STATUS.PENDING_PAY, AppointmentModel.STATUS.PAID, AppointmentModel.STATUS.IN_SERVICE] },
				isDeleted: { $ne: 1 }
			};
			if (excludeAppointmentId) {
				where._id = { $ne: excludeAppointmentId };
			}
			where.$or = [
				{ appointmentTime: { $gte: startTime, $lt: endTime } },
				{ appointmentEndTime: { $gt: startTime, $lte: endTime } },
				{ appointmentTime: { $lte: startTime }, appointmentEndTime: { $gte: endTime } }
			];
			const cnt = await AppointmentModel.count(where);
			if (cnt >= capacity) {
				throw new Error('ROOM_FULL:该房间已被约满，请选择其他房型');
			}
			return;
		}

		// 无容量配置时，沿用原有的门店级时间冲突校验（仅限已支付或服务中）
		let where = {
			storeId: storeId,
			status: { $in: [AppointmentModel.STATUS.PAID, AppointmentModel.STATUS.IN_SERVICE] },
			isDeleted: { $ne: 1 }
		};
		if (excludeAppointmentId) {
			where._id = { $ne: excludeAppointmentId };
		}

		// 检查时间重叠
		where.$or = [
			{
				appointmentTime: { $gte: startTime, $lt: endTime }
			},
			{
				appointmentEndTime: { $gt: startTime, $lte: endTime }
			},
			{
				appointmentTime: { $lte: startTime },
				appointmentEndTime: { $gte: endTime }
			}
		];

		const conflicts = await AppointmentModel.getAll(where);
		if (conflicts.length > 0) {
			throw new Error('该时间段已有预约，请选择其他时间');
		}
	}

	/**
	 * 丰富预约列表信息
	 * @param {Array} appointments 预约列表
	 * @returns {Array} 丰富后的预约列表
	 */
	async enrichAppointmentList(appointments) {
		const enrichedAppointments = [];
		
		for (let appointment of appointments) {
			try {
				const enriched = await this.enrichAppointmentDetail(appointment);
				enrichedAppointments.push(enriched);
			} catch (error) {
				console.error('丰富预约信息失败:', error);
				enrichedAppointments.push(appointment);
			}
		}
		
		return enrichedAppointments;
	}

	/**
	 * 丰富预约详情信息
	 * @param {Object} appointment 预约信息
	 * @returns {Object} 丰富后的预约信息
	 */
	async enrichAppointmentDetail(appointment) {
		// 获取门店信息
		const store = await StoreModel.getOne({ _id: appointment.storeId }, 'name,address,phone');
		
		// 获取服务信息
		const service = await ServiceModel.getOne({ _id: appointment.serviceId }, 'name,price,duration');
		
		// 获取宠物信息
		const pets = [];
		for (let petId of appointment.petIds) {
			const pet = await PetModel.getOne({ _id: petId }, 'name,species,breed,category,avatar,imageUrl,image,age,weight');
			if (pet) {
				pets.push(pet);
			}
		}

		return {
			...appointment,
			storeInfo: store,
			serviceInfo: service,
			petList: pets,
			petInfo: pets[0] || {} // 兼容旧版本
		};
	}

	/**
	 * 验证状态转换是否合法
	 * @param {number} fromStatus 原状态
	 * @param {number} toStatus 目标状态
	 * @returns {boolean} 是否合法
	 */
	isValidStatusTransition(fromStatus, toStatus) {
		const validTransitions = {
			[AppointmentModel.STATUS.PENDING_PAY]: [AppointmentModel.STATUS.PAID, AppointmentModel.STATUS.CANCELLED],
			[AppointmentModel.STATUS.PAID]: [AppointmentModel.STATUS.IN_SERVICE, AppointmentModel.STATUS.CANCELLED],
			[AppointmentModel.STATUS.IN_SERVICE]: [AppointmentModel.STATUS.COMPLETED],
			[AppointmentModel.STATUS.COMPLETED]: [],
			[AppointmentModel.STATUS.CANCELLED]: []
		};

		return validTransitions[fromStatus] && validTransitions[fromStatus].includes(toStatus);
	}

	/**
	 * 生成预约单号
	 * @returns {string} 预约单号
	 */
	generateAppointmentNumber() {
		const now = new Date();
		const year = now.getFullYear();
		const month = String(now.getMonth() + 1).padStart(2, '0');
		const day = String(now.getDate()).padStart(2, '0');
		const random = Math.random().toString(36).substr(2, 6).toUpperCase();
		
		return `APT${year}${month}${day}${random}`;
	}

	/**
	 * 生成唯一ID
	 * @returns {string} 唯一ID
	 */
	generateId() {
		return 'APT' + Date.now() + Math.random().toString(36).substr(2, 9);
	}

	/**
	 * 映射预约订单状态到充值订单状态
	 * @param {number} appointmentStatus 预约订单状态
	 * @returns {number|null} 充值订单状态
	 */
	mapAppointmentStatusToRechargeStatus(appointmentStatus) {
		// 预约状态：101待支付, 201已支付, 301服务中, 302已完成, 401已取消
		// 充值状态：101待支付, 201已支付, 301已取消, 401支付失败
		const statusMap = {
			[AppointmentModel.STATUS.PENDING_PAY]: RechargeModel.STATUS.PENDING_PAY, // 待支付
			[AppointmentModel.STATUS.PAID]: RechargeModel.STATUS.PAID, // 已支付
			[AppointmentModel.STATUS.CANCELLED]: RechargeModel.STATUS.CANCELLED, // 已取消
			// 服务中和已完成状态在充值订单中对应已支付
			[AppointmentModel.STATUS.IN_SERVICE]: RechargeModel.STATUS.PAID,
			[AppointmentModel.STATUS.COMPLETED]: RechargeModel.STATUS.PAID
		};
		return statusMap[appointmentStatus] || null;
	}

	/**
	 * 将充值订单转换为预约订单格式
	 * @param {Object} rechargeOrder 充值订单
	 * @returns {Object} 转换后的订单格式
	 */
	convertRechargeToAppointmentFormat(rechargeOrder) {
		// 映射充值状态到预约状态显示
		const getDisplayStatus = (rechargeStatus) => {
			switch (rechargeStatus) {
				case RechargeModel.STATUS.PENDING_PAY:
					return AppointmentModel.STATUS.PENDING_PAY; // 待支付
				case RechargeModel.STATUS.PAID:
					return AppointmentModel.STATUS.COMPLETED; // 已完成（充值成功）
				case RechargeModel.STATUS.CANCELLED:
					return AppointmentModel.STATUS.CANCELLED; // 已取消
				case RechargeModel.STATUS.FAILED:
					return AppointmentModel.STATUS.CANCELLED; // 失败显示为已取消
				default:
					return AppointmentModel.STATUS.PENDING_PAY;
			}
		};

		return {
			_id: rechargeOrder._id,
			appointmentNumber: rechargeOrder.orderNumber,
			orderType: 'recharge', // 标识为充值订单
			storeId: null,
			serviceId: null,
			petIds: [],
			appointmentTime: rechargeOrder.payTime || rechargeOrder.createTime,
			appointmentEndTime: rechargeOrder.payTime || rechargeOrder.createTime,
			status: getDisplayStatus(rechargeOrder.status),
			totalAmount: rechargeOrder.totalAmount,
			payAmount: rechargeOrder.totalAmount,
			createTime: rechargeOrder.createTime,
			// 充值订单特有信息
			rechargeInfo: {
				amount: rechargeOrder.amount,
				bonus: rechargeOrder.bonus,
				totalAmount: rechargeOrder.totalAmount
			},
			// 模拟门店信息（充值订单）
			storeInfo: {
				name: '账户充值',
				address: '线上充值服务',
				phone: ''
			},
			// 模拟服务信息（充值订单）
			serviceInfo: {
				name: `充值 ¥${(rechargeOrder.amount / 100).toFixed(2)}${rechargeOrder.bonus > 0 ? ` + 赠送 ¥${(rechargeOrder.bonus / 100).toFixed(2)}` : ''}`,
				price: rechargeOrder.totalAmount,
				duration: 0
			},
			petInfo: []
		};
	}
}

module.exports = AppointmentService;
